import React, { useCallback } from 'react';
import clsx from 'clsx';
import Link from 'next/link';

export interface MenuItem {
  key: string;
  icon: React.ReactNode;
  label: string;
  href?: string;
  target?: React.HTMLAttributeAnchorTarget;
  children?: MenuItem[];
  onClick?: (menuItem: MenuItem) => void;
}

export interface MenuProps {
  className?: string;
  selectedKey?: string;
  /**
   * 默认展开所有子菜单
   * @default false
   * @description 仅在子菜单存在时生效
   */
  allExpanded?: boolean;
  /**
   * 收起菜单，只展示图标
   * @default false
   */
  inlineCollapsed?: boolean;
  menus?: MenuItem[];
}

function MenuNoMemoized(props: MenuProps) {
  const { className, selectedKey, allExpanded, inlineCollapsed, menus } = props;

  const flattenMenus = useCallback((_menus: MenuItem[]): MenuItem[] => {
    return _menus.reduce((acc, menu) => {
      if (menu.children && menu.children.length > 0) {
        acc.push(...flattenMenus(menu.children));
      } else {
        acc.push(menu);
      }
      return acc;
    }, [] as MenuItem[]);
  }, []);

  const rescursion = useCallback(
    (_menus: MenuItem[]) => {
      let finalMenus = _menus;
      if (inlineCollapsed) {
        // 如果收起菜单，扁平化展示整个菜单，展示所有叶子节点
        finalMenus = flattenMenus(_menus);
      }
      return finalMenus.map((menu) => {
        const { key, icon, label, href, target, children, onClick } = menu;

        return (
          <li
            key={key}
            className={clsx(
              'relative w-full',
              (key === selectedKey || href === selectedKey) &&
                'bg-gradient-to-r from-transparent to-purple-200 dark:from-transparent dark:to-purple-950/50'
            )}
          >
            {children && children.length > 0 ? (
              <details open={allExpanded}>
                <summary>
                  {icon}
                  {label}
                </summary>
                <ul>{rescursion(children)}</ul>
              </details>
            ) : (
              <Link
                href={href ?? '#'}
                className={clsx('truncate', inlineCollapsed && 'justify-center')}
                target={target}
                title={label}
                onClick={() => onClick?.(menu)}
              >
                {icon}
                {!inlineCollapsed && label}
                {(key === selectedKey || href === selectedKey) && (
                  <span className="absolute top-1/2 right-0 -translate-y-1/2 w-1 h-5 bg-purple-500 rounded-s-md" />
                )}
              </Link>
            )}
          </li>
        );
      });
    },
    [allExpanded, flattenMenus, inlineCollapsed, selectedKey]
  );

  return (
    <ul
      role="menu"
      aria-label="menu"
      aria-orientation="vertical"
      className={clsx(
        'menu w-full px-0 text-gray-900 dark:text-gray-200',
        '[--menu-active-fg:var(--color-gray-400)] [--menu-active-bg:var(--color-gray-100)] [--color-base-content:var(--color-gray-400)]',
        'dark:[--menu-active-fg:var(--color-gray-500)] dark:[--menu-active-bg:var(--color-neutral-950)] dark:[--color-base-content:var(--color-neutral-600)]',
        '[&_li>a]:px-4 [&_li>a]:py-3 [&_details>summary]:px-4 [&_details>summary]:py-3 [&_li>*]:rounded-none [&_details>summary]:rounded-none',
        className
      )}
    >
      {menus?.length && rescursion(menus)}
    </ul>
  );
}

export const Menu = React.memo(MenuNoMemoized);
